#region File Info
// File: MainForm.cs
// Product: Ebnf Visualizer
// Types: 
//    class MainForm
// License:
// Copyright (C) 2010 Daniel Kuschny (http://www.coderline.net)
//
// This file is part of Ebnf Visualizer.
//
// Ebnf Visualizer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Ebnf Visualizer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Ebnf Visualizer. If not, see <http://www.gnu.org/licenses/>.
#endregion

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using EbnfVisualizer.Properties;
using Puzzle.SourceCode;

namespace EbnfVisualizer
{
    /// <summary>
    /// Das Hauptfenster der Anwendung.
    /// </summary>
    public partial class MainForm : Form
    {
        #region Felder
      
        private bool _autoRefresh;
        private readonly EbnfParser _parser;
        private Image _image;

        #endregion

        #region Eigenschaften

        /// <summary>
        /// Ruft das gerenderte Bild für die Grammatik ab oder legt dieses fest.
        /// </summary>
        /// <value>Das gerenderte Bild..</value>
        public Image Image
        {
            get
            {
                return _image;
            }
            set
            {
                _image = value;
                // Oberfläche aktualisieren
                pictureBox1.Image = value;
                pictureBox1.Size = value != null
                                       ? value.Size +
                                          new Size(pictureBox1.Padding.Horizontal, pictureBox1.Padding.Vertical)
                                       : new Size(10, 10);
                btnCopy.Enabled = value != null;
                btnSave.Enabled = value != null;
            }
        } 

        #endregion

        #region Konstruktor

        /// <summary>
        /// Initialisiert eine neue Instanz der <see cref="MainForm"/> Klasse.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
            _parser = new EbnfParser();
        }

        #endregion

        #region Methoden

        /// <summary>
        /// Wird ausgelöst wenn der Button für die Aktualisierung des Bildes geklickt wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnUpdateClick(object sender, EventArgs e)
        {
            // Bild Rendern
            _parser.Title = txtTitle.Text;
            Image = _parser.Parse(syntaxDocument1.Text);

            // Fehler im Coding markieren
            syntaxDocument1.FormatRanges.Clear();
            if (_parser.Error != null)
            {
                TextPoint pt = syntaxDocument1.IntPosToPoint(_parser.Error.Position);
                FormatRange range = new FormatRange(new TextRange(pt.X, pt.Y, pt.X, pt.Y), Color.Red);
                syntaxDocument1.FormatRanges.Add(range);
            }

            // Regeln für die Auswahl anlegen
            ToolStripItem all = btnAllRules;
            tddRule.DropDownItems.Clear();
            tddRule.DropDownItems.Add(all);
            foreach (string rule in _parser.Rules)
            {
                tddRule.DropDownItems.Add(rule);
            }

            // Aktuelle Regel selektieren wenn verfügbar
            if (!string.IsNullOrEmpty(_parser.CurrentRule))
                tddRule.Text = _parser.CurrentRule;
            else
                btnAllRules.PerformClick();
        }

        /// <summary>
        /// Wird ausgelöst wenn der Button für das Speichern des Bildes geklickt wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnSaveClick(object sender, EventArgs e)
        {
            if (Image == null) return;
            try
            {
                SaveFileDialog dlg = new SaveFileDialog { Filter = "PNG Bild (*.png)|*.png" };
                if (dlg.ShowDialog(this) == DialogResult.OK)
                {
                    Image.Save(dlg.FileName, ImageFormat.Png);
                    MessageBox.Show("Das Bild wurde erfolgreich in die Datei gespeichert.", "Bild kopiert!",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    "Fehler beim Kopieren des Bildes in die Zwischenablage: " + ex.Message,
                    "Bild nicht kopiert!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Wird ausgelöst wenn der Button für die Kopieren des Bildes geklickt wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnCopyClick(object sender, EventArgs e)
        {
            if (Image == null) return;
            try
            {
                Clipboard.SetImage(Image);
                MessageBox.Show("Das Bild wurde erfolgreich in die Zwischenablage kopiert. " +
                                "Sie können es nun in anderen Anwendungen einfügen", "Bild kopiert!",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Fehler beim Kopieren des Bildes in die Zwischenablage: " + ex.Message,
                                "Bild nicht kopiert!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Wird ausgelöst wenn der Button für das Ändern des Auto-Updates geklickt wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnAutoRefreshChanged(object sender, EventArgs e)
        {
            _autoRefresh = btnAutoRefresh.Checked;
        }

        /// <summary>
        /// Wird ausgelöst wenn das Fenster fertig geladen wurde geklickt wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnFormLoad(object sender, EventArgs e)
        {
            // Autorefresh-Status
            OnAutoRefreshChanged(sender, e);

            // Templates
            string[][] templates = new string[2][];
            templates[0] = new[] { "Buchstaben", Resources.Buchstaben };
            templates[1] = new[] { "Ziffern", Resources.Ziffer };
            foreach (string[] s in templates)
            {
                ToolStripMenuItem item = new ToolStripMenuItem(s[0]) { Tag = s[1] };
                item.Click += OnTemplateInsert;
                btnTemplates.DropDownItems.Add(item);
            }

            // Anfangsbild
            btnUpdateImg.PerformButtonClick();
        }

        /// <summary>
        /// Wird ausgelöst wenn der Button für das Einfügen eines Templates geklickt wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnTemplateInsert(object sender, EventArgs e)
        {
            ToolStripMenuItem item = sender as ToolStripMenuItem;
            if (item != null)
            {
                syntaxDocument1.Text += Environment.NewLine + item.Tag;
            }
        }

        /// <summary>
        /// Wird ausgelöst wenn der Quellcode der Grammatik geändert wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnSyntaxDocumentTextChange(object sender, EventArgs e)
        {
            if (_autoRefresh)
            {
                btnUpdateImg.PerformButtonClick();
            }
        }

        /// <summary>
        /// Wird ausgelöst wenn der Button für das Auswählen eine Regel geklickt wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnRuleSelected(object sender, ToolStripItemClickedEventArgs e)
        {
            ToolStripMenuItem item = e.ClickedItem as ToolStripMenuItem;
            if (item != null && item == btnAllRules)
            {
                Image = _parser.ShowAllRules();
                tddRule.Text = item.Text;
            }
            else if (item != null)
            {
                Image = _parser.ShowRule(item.Text);
                tddRule.Text = item.Text;
            }
        }

        /// <summary>
        /// Wird ausgelöst wenn der Titel für das Bild geändert wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnTitleChanged(object sender, EventArgs e)
        {
            if (_autoRefresh)
            {
                btnUpdateImg.PerformButtonClick();
            }
        }

        /// <summary>
        /// Wird ausgelöst wenn der Button für das Anzeigen des Hilfe geklickt wird. 
        /// </summary>
        /// <param name="sender">Der Sender.</param>
        /// <param name="e">Eine Instanz der <see cref="EventArgs"/> Klasse die die Eventdaten beinhält.</param>
        private void OnHelpClick(object sender, EventArgs e)
        {
            using (AboutForm about = new AboutForm())
            {
                about.ShowDialog(this);
            }
        } 

        #endregion
    }
}
